#region File Description
//-----------------------------------------------------------------------------
// GameplayScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using GameStateManagement;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Media;
using TermitesMagnets.Targets;
#endregion

namespace TermitesMagnets
{
    /// <summary>
    /// This screen implements the actual game logic. It is just a
    /// placeholder to get the idea across: you'll probably want to
    /// put some more interesting gameplay in here!
    /// </summary>
    public class GameplayScreen : GameScreen
    {
        #region Fields

        ContentManager content;
        SpriteFont gameFont;
        float pauseAlpha;
        InputAction pauseAction;

        public float GameSpeed = 5;
        private int magnetIndex = 0;
        private List<Level> levels;
        private Level currentLevel;
        private int lastScrolWheel = 0;
        private int currentLevelIndex = 0;
        private SpriteFont font;
        public int screenWitdh = 800;
        public int screenHeight = 600;
        private float timeSinceLastKey;
        private float KEY_DELAY = 0.2f;
        public static Random Rand;
        public static GameplayScreen GlobalGame;

        public SpriteBatch SpriteBatch { get { return ScreenManager.SpriteBatch; ; } }
        public Level CurrentLevel { get { return currentLevel; } }
        public SpriteFont Font { get { return font; } }

        public static float seconds = 0;
        public static float interval = 1000f;
        public bool intervalFlagHigh = false;
        Microsoft.Xna.Framework.Media.Song backgroundMusic;
        bool musicStarted = false;
        private SoundEffect prepareToFight;
        private SoundEffect humiliation;
        private SoundEffect unstopable;
        public static bool MusicEnabled = true;
        public static bool SoundsEnabled = true;
        public static int Difficulty = 2;


        #endregion

        #region Initialization


        public static void PlaySound(SoundEffect sound)
        {
            if (SoundsEnabled)
                sound.Play();
        }

        /// <summary>
        /// Constructor.
        /// </summary>
        public GameplayScreen()
        {
            GlobalGame = this;
            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);

            pauseAction = new InputAction(
                new Buttons[] { Buttons.Start, Buttons.Back },
                new Keys[] { Keys.Escape },
                true);
        }


        /// <summary>
        /// Load graphics content for the game.
        /// </summary>
        public override void Activate(bool instancePreserved)
        {
            if (!instancePreserved)
            {
                if (content == null)
                    content = new ContentManager(ScreenManager.Game.Services, "Content");

                gameFont = content.Load<SpriteFont>(@"Fonts\gamefont");

                Termite.LoadContent(content);
                Magnet.LoadContent(content);
                Pwu.LoadContent(content);
                TargetRect.LoadContent(content);
                Obstacle.LoadContent(content);
                GameBackground.LoadContent(content);
                ParticleSystemManager.LoadContent(content);
                levels = new List<Level> { new Level0(this), new Level1(this), new Level2(this), new Level3(this), 
                    new Level4(this), new Level5(this), new Level6(this) };
                switchLevel(0);
                font = content.Load<SpriteFont>(@"Fonts\myFont");
                //backgroundmusic = Content.Load<Song>(@"Music\a");
                prepareToFight = content.Load<SoundEffect>(@"Sounds\prepareToFight");
                unstopable = content.Load<SoundEffect>(@"Sounds\Unstopable");
                humiliation = content.Load<SoundEffect>(@"Sounds\Humiliation");
                backgroundMusic = content.Load<Song>(@"Music\music1");
                MediaPlayer.IsRepeating = true; 
                // A real game would probably have more content than this sample, so
                // it would take longer to load. We simulate that by delaying for a
                // while, giving you a chance to admire the beautiful loading screen.
                //Thread.Sleep(1000);

                // once the load has finished, we use ResetElapsedTime to tell the game's
                // timing mechanism that we have just finished a very long frame, and that
                // it should not try to catch up.
                ScreenManager.Game.ResetElapsedTime();
            }
        }


        public override void Deactivate()
        {
            base.Deactivate();
        }


        /// <summary>
        /// Unload graphics content used by the game.
        /// </summary>
        public override void Unload()
        {
            content.Unload();

        }


        #endregion

        #region Update and Draw


        /// <summary>
        /// Updates the state of the game. This method checks the GameScreen.IsActive
        /// property, so the game will stop updating when the pause menu is active,
        /// or if you tab away to a different application.
        /// </summary>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, false);

            if (!musicStarted && GameplayScreen.MusicEnabled)
            {
                MediaPlayer.Play(backgroundMusic);
                MediaPlayer.Volume = 0.3f;
                musicStarted = true;
            }

            // Gradually fade in or out depending on whether we are covered by the pause screen.
            if (coveredByOtherScreen)
                pauseAlpha = Math.Min(pauseAlpha + 1f / 32, 1);
            else
                pauseAlpha = Math.Max(pauseAlpha - 1f / 32, 0);

            if (IsActive)
            {
                // Apply some random jitter to make the enemy move around.
                float timeDiff = (float)gameTime.ElapsedGameTime.TotalSeconds;
                seconds += timeDiff;
                timeSinceLastKey += timeDiff;

                #region endGameLogic

                bool won = true;

                foreach (TargetRect target in currentLevel.HumanTargets)
                {
                    if (!target.TargetReached())
                    {
                        won = false;
                        break;
                    }
                }

                bool lost = false;
                if (currentLevel.AiTargets.Count > 0)
                {
                    foreach (TargetRect target in currentLevel.AiTargets)
                    {
                        if (target.TargetReached())
                        {
                            lost = true;
                            break;
                        }
                    }
                }

                if (won)
                {
                    GameplayScreen.PlaySound(unstopable);
                    timeSinceLastKey = 0;
                    currentLevel.ClearLevel();
                    currentLevelIndex += 1;
                    currentLevelIndex = currentLevelIndex % levels.Count;
                    switchLevel(currentLevelIndex);

                }
                else if (lost)
                {
                    GameplayScreen.PlaySound(humiliation);
                    timeSinceLastKey = 0;
                    currentLevel.ClearLevel();
                    switchLevel(currentLevelIndex);
                }

                #endregion

            }
        }


        /// <summary>
        /// Lets the game respond to player input. Unlike the Update method,
        /// this will only be called when the gameplay screen is active.
        /// </summary>
        public override void HandleInput(GameTime gameTime, InputState input)
        {
            if (input == null)
                throw new ArgumentNullException("input");

            // Look up inputs for the active player profile.
            int playerIndex = (int)ControllingPlayer.Value;

            KeyboardState keyboardState = input.CurrentKeyboardStates[playerIndex];
            GamePadState gamePadState = input.CurrentGamePadStates[playerIndex];

            // The game pauses either if the user presses the pause button, or if
            // they unplug the active gamepad. This requires us to keep track of
            // whether a gamepad was ever plugged in, because we don't want to pause
            // on PC if they are playing with a keyboard and have no gamepad at all!
            bool gamePadDisconnected = !gamePadState.IsConnected &&
                                       input.GamePadWasConnected[playerIndex];

            PlayerIndex player;
            if (pauseAction.Evaluate(input, ControllingPlayer, out player) || gamePadDisconnected)
            {

                ScreenManager.AddScreen(new PauseMenuScreen(), ControllingPlayer);
            }
            else
            {
                #region cheats
                if (keyboardState.IsKeyDown(Keys.Space) && keyboardState.IsKeyDown(Keys.D0) && timeSinceLastKey > KEY_DELAY)
                {
                    timeSinceLastKey = 0;
                    switchLevel(0);
                }
                if (keyboardState.IsKeyDown(Keys.Space) && keyboardState.IsKeyDown(Keys.D1) && timeSinceLastKey > KEY_DELAY)
                {
                    timeSinceLastKey = 0;
                    switchLevel(1);
                }

                if (keyboardState.IsKeyDown(Keys.Space) && keyboardState.IsKeyDown(Keys.D2) && timeSinceLastKey > KEY_DELAY)
                {
                    timeSinceLastKey = 0;
                    switchLevel(2);
                }
                if (keyboardState.IsKeyDown(Keys.Space) && keyboardState.IsKeyDown(Keys.D3) && timeSinceLastKey > KEY_DELAY)
                {
                    timeSinceLastKey = 0;
                    switchLevel(3);
                }
                if (keyboardState.IsKeyDown(Keys.Space) && keyboardState.IsKeyDown(Keys.D4) && timeSinceLastKey > KEY_DELAY)
                {
                    timeSinceLastKey = 0;
                    switchLevel(4);
                }
                if (keyboardState.IsKeyDown(Keys.Space) && keyboardState.IsKeyDown(Keys.D5) && timeSinceLastKey > KEY_DELAY)
                {
                    timeSinceLastKey = 0;
                    switchLevel(5);
                }
                if (keyboardState.IsKeyDown(Keys.Space) && keyboardState.IsKeyDown(Keys.D6) && timeSinceLastKey > KEY_DELAY)
                {
                    timeSinceLastKey = 0;
                    switchLevel(6);
                }
#endregion
                Magnet selectedMagnet = currentLevel.Magnets[magnetIndex];
                selectedMagnet.Selected = true;
                if (keyboardState.IsKeyDown(Keys.Space) && timeSinceLastKey > KEY_DELAY)
                {
                    timeSinceLastKey = 0;
                    selectedMagnet.IsEnabled = !selectedMagnet.IsEnabled;
                }
            }
        }


        /// <summary>
        /// Draws the gameplay screen.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);
            

            // If the game is transitioning on or off, fade it out to black.
            if (TransitionPosition > 0 || pauseAlpha > 0)
            {
                float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2);

                ScreenManager.FadeBackBufferToBlack(alpha);
            }
        }

        #endregion

        private void switchLevel(int index)
        {
            if (index >= levels.Count)
                return;
            if (currentLevel != null)
                currentLevel.ClearLevel();
            magnetIndex = 0;
            currentLevelIndex = index;
            currentLevel = levels[index];
            currentLevel.Activate();
            if (prepareToFight != null)
                GameplayScreen.PlaySound(prepareToFight);
        }

    }
}
